/**
 * @file 公共检索列表的出口
 * @author its-wild(https://gitee.com/its-wild)
 * @date 2022/08/17
 */
import { ref, Ref, reactive } from 'vue'
import { message } from 'ant-design-vue'
import type { FormInstance } from 'ant-design-vue'
import { isUndefinedEmptyNull } from '@/utils/base'

/**
 * 检索区表单栅格
 */
export interface IColSpan {
  xs?: number
  sm?: number
  md?: number
  lg?: number
  xl?: number
  xxl?: number
}

export interface IPagination {
  /**
   * 当前页面码
   */
  current: number
  /**
   * 分页条数，默认10
   */
  pageSize: number
  /**
   * 指定每页可以显示多少条
   */
  pageSizeOptions: string[]
  /**
   * 用于显示数据总量和当前数据顺序
   */
  showTotal: (total: number, range: number[]) => string
  /**
   * 是否可以快速跳转至某页
   */
  showQuickJumper: boolean
  /**
   * 是否可以改变 pageSize
   */
  showSizeChanger: boolean
  /**
   * 数据总数
   */
  total: number
}

/**
 * 1. 添加
 * 2. 编辑
 */
export type TEdit = 1 | 2

export interface IEditForm {
  /**
   * 添加
   */
  add?: (record: any) => void
  /**
   * 编辑
   */
  edit?: (record: any) => void
}

export interface ISearchList {
  /**
   * 检索条件的栅格
   */
  colSpan: IColSpan

  /**
   * 加载状态
   */
  loading: Ref<boolean>

  /**
   * 设置加载状态
   */
  setLoading: (val: boolean) => void

  /**
   * 分页参数
   */
  pagination: IPagination

  /**
   * 列表数据
   */
  list: Ref<any[]>

  /**
   * 设置列表数据
   */
  setList: (val: any) => void

  /**
   * 加载列表数据
   */
  loadList: () => void

  /**
   * 分页、排序、筛选变化时触发
   * @param {object} pagination 分页信息
   * @return {void}
   */
  handleTableChange: (pagination: any) => void

  /**
   * 检索表单对象
   */
  searchFormRef: Ref<FormInstance | undefined>

  /**
   * 检索表单数据
   */
  searchFormState: any

  /**
   * 检索
   */
  onSearch: () => void

  /**
   * 重置
   */
  onResetSearch: () => void

  /**
   * 展示更多检索条件
   */
  showMoreSearch: Ref<boolean>

  /**
   * 弹框对象
   */
  editFormRef: Ref<IEditForm | undefined>

  /**
   * 是否显示添加/编辑表单
   */
  showForm?: Ref<boolean>

  /**
   * 设置是否显示添加/编辑表单
   */
  setShowForm?: (val: boolean) => void

  /**
   * 当前编辑数据
   */
  mdl?: Ref<any>

  /**
   * 设置当前编辑数据
   */
  setMdl?: (val: any) => void

  /**
   * 编辑
   */
  onEdit?: (record?: any) => void

  /**
   * 添加或编辑点确认
   */
  onOk?: () => void

  /**
   * 删除
   */
  onDelete?: (record: any) => void
}

/**
 * 基础信息
 */
interface IBase {
  /**
   * 列表查询参数
   */
  params?: any

  /**
   * 加载列表方法
   */
  getList: <IListRes>(params?: any) => Promise<IListRes>

  /**
   * 列表删除
   */
  del?: (data: any) => void
}

/**
 * 列表接口返回数据
 */
export interface IListRes {
  items: any[]
  total: number
}

/**
 * 带检索的表格基础设置
 * @param base 基础信息
 * @returns 列表所需要的基本配置
 */
export default function searchTable<IListItem>(base: IBase): ISearchList {
  const { params, getList, del } = base

  const colSpan: IColSpan = {
    md: 12,
    lg: 8,
    xl: 6,
    xxl: 4
  }

  // 检索表单对象
  const searchFormRef = ref<FormInstance>()

  const searchFormState = reactive(params)

  const showMoreSearch = ref(false)

  const loading = ref<boolean>(false)
  const setLoading = (val: boolean) => {
    loading.value = val
  }

  // 列表
  const list = ref<IListItem[]>([]) as Ref<IListItem[]>
  const setList = (val: IListItem[]) => {
    list.value = val
  }

  // 加载列表数据
  const loadList = async () => {
    const data = {
      page: pagination.current,
      limit: pagination.pageSize,
      ...searchFormState
    }

    for (const key in data) {
      if (isUndefinedEmptyNull(data[key])) {
        delete data[key]
      }
    }

    if (!getList) {
      message.warning('请设置 getList 方法~')
      return
    }

    setLoading(true)
    const res: IListRes = await getList<IListRes>(data)
    setLoading(false)
    const { items, total } = res
    pagination.total = total || 0
    setList(items || [])
    document.querySelector('.global-container')?.scrollTo(0, 0)
  }

  const pagination = reactive({
    current: 1,
    pageSize: 10,
    pageSizeOptions: ['10', '20', '30', '50', '100'],
    showTotal: (total: number, range: number[]) => {
      return range[0] + '-' + range[1] + ' 共' + total + '条'
    },
    showQuickJumper: true,
    showSizeChanger: true,
    total: 0,
  })

  /**
   * 检索
   */
  const onSearch = () => {
    pagination.current = 1
    loadList()
  }

  /**
   * 重置
   */
  const onResetSearch = () => {
    searchFormRef.value?.resetFields()
    onSearch()
  }

  // 分页、排序、筛选变化时触发
  const handleTableChange = (pgntn: IPagination) => {
    pagination.pageSize = pgntn.pageSize
    pagination.current = pgntn.current
    loadList()
  }

  // 删除
  const onDelete = async (data: any) => {
    if (del) {
      await del(data)
      // 加载当前条件下第一页
      onSearch()
    }
  }

  // 是否显示添加/编辑表单
  const showForm = ref(false)
  const setShowForm = (val: boolean) => {
    showForm.value = val
  }

  // 添加/编辑
  const editFormRef = ref<IEditForm>()
  const mdl = ref({})
  const setMdl = (val: any) => {
    mdl.value = val
  }
  const onEdit = (type: TEdit, record?: any) => {
    setMdl(record)
    setShowForm(true)
    if (editFormRef.value) {
      if (type === 2 && editFormRef.value.edit) {
        editFormRef.value.edit(record)
      } else if (type === 1 && editFormRef.value.add) {
        editFormRef.value.add(record)
      }
    }
  }

  // 添加或编辑点确认
  const onOk = () => {
    setShowForm(false)
    loadList()
  }

  return {
    colSpan,
    showMoreSearch,
    loading,
    setLoading,
    list,
    setList,
    loadList,
    pagination,
    searchFormRef,
    searchFormState,
    onSearch,
    onResetSearch,
    handleTableChange,
    onDelete,
    onEdit,
    onOk,
    editFormRef,
    showForm,
    mdl,
  }
}
